﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;
using _10_HPBar.GameFrame;
using _10_HPBar.GameFrame.Interface;
using _10_HPBar.GameFrame.System;
using _10_HPBar.Items;
using _10_HPBar.Scene;
using _10_HPBar.Tool;

namespace _10_HPBar.CharacterBase
{
    internal class Player : Character
    {
        enum State
        {
            None, Up, Down, Left, Right, Enter
        }

        Direction dir;
        Action<GameObject> interactionAction;
        State state;
        SceneMain scene;
        CombatSystem combat;
        InventorySystem inventory;
        GameObject interactionObj;

        public Player(string name, int hp, int mp, int atk, int def, Pos pos, Map map, string display, InfoSystem info, SceneMain scene, CombatSystem combat)
            : base(name, hp, mp, atk, def, pos, map, display, info)
        {
            this.scene = scene;
            this.combat = combat;
            inventory = new InventorySystem(24, 14, 16, 7,this);
        }

        public override void Render()
        {
            switch (dir)
            {
                case Direction.Up:
                    display = "↑";
                    break;
                case Direction.Down:
                    display = "↓";
                    break;
                case Direction.Left:
                    display = "←";
                    break;
                case Direction.Right:
                    display = "→";
                    break;
            }
            base.Render();
            inventory.Render();
        }

        void Move(Direction dir)
        {
            if (!CanMove(dir))
                return;
            if(map.GetType(Pos) != Map.Type.Upstairs &&
               map.GetType(Pos) != Map.Type.Downstairs &&
               map.GetType(Pos) != Map.Type.Spawn &&
               map.GetType(Pos) != Map.Type.Item)
               map.SetType(Pos, Map.Type.Empty);
            Pos temp = Pos;
            Utility.MyPrint("  ", Pos.x + map.offsetX, Pos.y + map.offsetY);
            switch (dir)
            {
                case Direction.Up:
                    temp.y--;
                    break;
                case Direction.Down:
                    temp.y++;
                    break;
                case Direction.Left:
                    temp.x--;
                    break;
                case Direction.Right:
                    temp.x++;
                    break;
            }
            Pos = temp;
            if (map.GetType(Pos) != Map.Type.Upstairs &&
                map.GetType(Pos) != Map.Type.Downstairs &&
                map.GetType(Pos) != Map.Type.Spawn &&
                map.GetType(Pos) != Map.Type.Item)
                map.SetType(Pos, Map.Type.Player);
            CheckEnemy();
            CheackTreasure();
            CheackPortal();
            //UpDownstairs(Pos);
            //PickUp(Pos);
        }

        bool CanMove(Direction dir)
        {
            return map.GetType(GetNextPos(dir)) != Map.Type.Downstairs
                && map.GetType(GetNextPos(dir)) != Map.Type.Wall
                && map.GetType(GetNextPos(dir)) != Map.Type.Upstairs
                /*&& map.GetType(GetNextPos(dir)) != Map.Type.Box*/;
        }

        void ChangeDir(Direction dir)
        {
            this.dir = dir;
        }

        Pos GetNextPos(Direction dir)
        {
            Pos next = Pos;
            switch (dir)
            {
                case Direction.Up:
                    next.y--;
                    break;
                case Direction.Down:
                    next.y++;
                    break;
                case Direction.Left:
                    next.x--;
                    break;
                case Direction.Right:
                    next.x++;
                    break;
            }
            return next;
        }

        // 告诉外界 我在和哪个点交互
        void Interaction()
        {
            interactionAction.Invoke(interactionObj);
            //UpDownstairs(GetNextPos(dir));
            PickUp(GetNextPos(dir));
        }

        public void AddInteractionAction(Action<GameObject> action)
        {
            interactionAction += action;
        }

        public void Input()
        {
            inventory.Input();
            // 测试用
            if (Game.input.IsKeyPressed(ConsoleKey.M))
            {
                switch (Game.rand.Next(5))
                {
                    case 0:
                        inventory.Add(new Armor());
                        break;
                    case 1:
                        inventory.Add(new BluePotion());
                        break;
                    case 2:
                        inventory.Add(new Key());
                        break;
                    case 3:
                        inventory.Add(new RedPotion());
                        break;
                    case 4:
                        inventory.Add(new Sword());
                        break;
                }
            }

            state = State.None;
            if (IsDialoging || IsCombating) return;

            if (Game.input.IsKeyPressed(ConsoleKey.W))
            {
                state = State.Up;
            }
            if (Game.input.IsKeyPressed(ConsoleKey.S))
            {
                state = State.Down;
            }
            if (Game.input.IsKeyPressed(ConsoleKey.A))
            {
                state = State.Left;
            }
            if (Game.input.IsKeyPressed(ConsoleKey.D))
            {
                state = State.Right;
            }
            if (Game.input.IsKeyPressed(ConsoleKey.Enter))
            {
                state = State.Enter;
            }
        }

        public void Update()
        {
            switch (state)
            {
                case State.Up:
                    ChangeDir(Direction.Up);
                    Move(Direction.Up);
                    break;
                case State.Down:
                    ChangeDir(Direction.Down);
                    Move(Direction.Down);
                    break;
                case State.Left:
                    ChangeDir(Direction.Left);
                    Move(Direction.Left);
                    break;
                case State.Right:
                    ChangeDir(Direction.Right);
                    Move(Direction.Right);
                    break;
                case State.Enter:
                    Interaction();
                    break;
            }
        }

        void CheckEnemy()
        {
            GameObject? e = null;
            scene.collision.IsCollision(this, out e);
            if (e != null && e.GetType() == typeof(Enemy))
            {
                info.AddInfo($"{Name}与{((Enemy)e).Name}遭遇了！");
                combat.StartCombat(this, ((Enemy)e));
            }
        }

        void CheackTreasure()
        {
            GameObject? t = null;
            scene.collision.IsCollision(this, out t);
            if (t != null && t.GetType() == typeof(Treasure))
            {
               interactionObj = t;
            }
        }

        void CheackPortal()
        {
            GameObject? p = null;
            scene.collision.IsCollision(this, out p);
            if (p != null && p.GetType() == typeof(Treasure))
            {
                map.ChangeMapByName(((Portal)p).Target.map);
                Pos = new Pos(((Portal)p).Target.x, ((Portal)p).Target.y);
            }
        }

        public void SetPos(Pos pos)
        {
            Pos = pos;
        }

        //void UpDownstairs(Pos pos)
        //{
        //    int index = -1;
        //    if (map.GetType(pos) == Map.Type.Upstairs)
        //    {
        //        // 判断有没有对应楼层钥匙
        //        index = map.ChangeNextMap(true);
        //        info.AddInfo($"{Name}上到了{index+1}层");
        //    }
        //    else if (map.GetType(pos) == Map.Type.Downstairs)
        //    {
        //        index = map.ChangeNextMap(false);
        //        info.AddInfo($"{Name}下到了{index+1}层");
        //    }
        //}

        void PickUp(Pos pos)
        {
            if(map.GetType(pos) == Map.Type.Item)
            {
                info.AddInfo($"拾取了道具",ConsoleColor.Cyan);
                // 往背包添加物品

                // 并且销毁地图上的物品
                map.SetType(pos, Map.Type.Empty);
                Utility.MyPrint("  ", pos.x + map.offsetX, pos.y+map.offsetY);
            }
        }
    }
}